{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "99b955e5",
   "metadata": {},
   "source": [
    "# Intro to Bricks\n",
    "\n",
    "The goal of this notebook is to introduce you to the concept of bricks. Bricks are functions that live in `unstructured` and are the primary public API for the library. There are three types of bricks in `unstructured`, corresponding to the different stages of document pre-processing: partitioning, cleaning, and staging. At the conclusion of this notebook, you should be able to do the following:\n",
    "\n",
    "- [Extract content from a document using partitioning bricks](#partition)\n",
    "- [Remove unwanted content from document elements using cleaning bricks](#cleaning)\n",
    "- [Preparing data for downstream use cases using staging bricks](#staging)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "3908be82",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import pathlib\n",
    "\n",
    "DIRECTORY = os.path.abspath(\"\")\n",
    "EXAMPLE_DOCS_DIRECTORY = os.path.join(DIRECTORY, \"..\", \"..\", \"example-docs\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d0842e87",
   "metadata": {},
   "source": [
    "## Partitioning bricks  <a id=\"partition\"></a>\n",
    "\n",
    "Partitioning bricks in `unstructured` allow users to extract structured content from a raw unstructured document. As we covered in the [core concepts notebook](https://github.com/Unstructured-IO/unstructured/blob/main/examples/training/0-Core%20Concepts.ipynb), partitioning bricks break a document down into elements such as `Title`, `NarrativeText`, and `ListItem`, enabling users to decide what content they'd like to keep for their particular application. If you're training a summarization model, for example, you may only be interested in `NarrativeText`.\n",
    "\n",
    "The easiest way to partition documents in `unstructured` is to use the `partition` brick. If you call the `partition` brick, `unstructured` will use `libmagic` to automatically determine the file type and invoke the appropriate `partition` function. As shown in the examples below, the `partition` function accepts both filenames and file-like objects as input. `partition` also has some includes some optional kwargs. For example, if you set `include_page_breaks=True`, the output will include `PageBreak` elements if the filetype supports it. See the\n",
    "[`unstructured` documentation](https://unstructured-io.github.io/unstructured/bricks.html#partition) for full details on available options."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "8bbb73c0",
   "metadata": {},
   "outputs": [],
   "source": [
    "from unstructured.partition.auto import partition\n",
    "\n",
    "filename = os.path.join(EXAMPLE_DOCS_DIRECTORY, \"layout-parser-paper-fast.pdf\")\n",
    "elements = partition(filename=filename)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "5319593c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "LayoutParser : A Uniﬁed Toolkit for Deep Learning Based Document Image Analysis\n",
      "\n",
      "Zejiang Shen 1 ( (ea)\n",
      " ), Ruochen Zhang 2 , Melissa Dell 3 , Benjamin Charles Germain Lee 4 , Jacob Carlson 3 , and Weining Li 5\n",
      "\n",
      "Allen Institute for AI shannons@allenai.org\n",
      "\n",
      "Brown University ruochen zhang@brown.edu\n",
      "\n",
      "Harvard University { melissadell,jacob carlson } @fas.harvard.edu\n",
      "\n",
      "University of Washington bcgl@cs.washington.edu\n",
      "\n",
      "University of Waterloo w\n",
      "\n",
      "li@uwaterloo.ca\n",
      "\n",
      "Abstract. Recent advances in document image analysis (DIA) have been primarily driven by the application of neural networks. Ideally, research outcomes could be easily deployed in production and extended for further investigation. However, various factors like loosely organized codebases and sophisticated model conﬁgurations complicate the easy reuse of im- portant innovations by a wide audience. Though there have been on-going eﬀorts to improve reusability and simplify deep learning (DL) model development in disciplines like natural language processing and computer vision, none of them are optimized for challenges in the domain of DIA. This represents a major gap in the existing toolkit, as DIA is central to academic research across a wide range of disciplines in the social sciences and humanities. This paper introduces LayoutParser , an open-source library for streamlining the usage of DL in DIA research and applica- tions. The core LayoutParser library comes with a set of simple and intuitive interfaces for applying and customizing DL models for layout de- tection, character recognition, and many other document processing tasks. To promote extensibility, LayoutParser also incorporates a community platform for sharing both pre-trained models and full document digiti- zation pipelines. We demonstrate that LayoutParser is helpful for both lightweight and large-scale digitization pipelines in real-word use cases. The library is publicly available at https://layout-parser.github.io\n",
      "\n",
      "Keywords: Document Image Analysis · Deep Learning · Layout Analysis · Character Recognition · Open Source library · Toolkit.\n"
     ]
    }
   ],
   "source": [
    "print(\"\\n\\n\".join([str(el) for el in elements][:10]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "8de9bee1",
   "metadata": {},
   "outputs": [],
   "source": [
    "with open(filename, \"rb\") as f:\n",
    "    elements = partition(file=f, include_page_breaks=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "75c6c73c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "University of Washington bcgl@cs.washington.edu\n",
      "\n",
      "University of Waterloo w\n",
      "\n",
      "li@uwaterloo.ca\n",
      "\n",
      "Abstract. Recent advances in document image analysis (DIA) have been primarily driven by the application of neural networks. Ideally, research outcomes could be easily deployed in production and extended for further investigation. However, various factors like loosely organized codebases and sophisticated model conﬁgurations complicate the easy reuse of im- portant innovations by a wide audience. Though there have been on-going eﬀorts to improve reusability and simplify deep learning (DL) model development in disciplines like natural language processing and computer vision, none of them are optimized for challenges in the domain of DIA. This represents a major gap in the existing toolkit, as DIA is central to academic research across a wide range of disciplines in the social sciences and humanities. This paper introduces LayoutParser , an open-source library for streamlining the usage of DL in DIA research and applica- tions. The core LayoutParser library comes with a set of simple and intuitive interfaces for applying and customizing DL models for layout de- tection, character recognition, and many other document processing tasks. To promote extensibility, LayoutParser also incorporates a community platform for sharing both pre-trained models and full document digiti- zation pipelines. We demonstrate that LayoutParser is helpful for both lightweight and large-scale digitization pipelines in real-word use cases. The library is publicly available at https://layout-parser.github.io\n",
      "\n",
      "Keywords: Document Image Analysis · Deep Learning · Layout Analysis · Character Recognition · Open Source library · Toolkit.\n",
      "\n",
      "Introduction\n",
      "\n",
      "Deep Learning(DL)-based approaches are the state-of-the-art for a wide range of document image analysis (DIA) tasks including document image classiﬁcation [11,\n",
      "\n",
      "<PAGE BREAK>\n",
      "\n",
      "37], layout detection [38, 22], table detection [26], and scene text detection [4]. A generalized learning-based framework dramatically reduces the need for the manual speciﬁcation of complicated rules, which is the status quo with traditional methods. DL has the potential to transform DIA pipelines and beneﬁt a broad spectrum of large-scale document digitization projects.\n",
      "\n",
      "However, there are several practical diﬃculties for taking advantages of re- cent advances in DL-based methods: 1) DL models are notoriously convoluted for reuse and extension. Existing models are developed using distinct frame- works like TensorFlow [1] or PyTorch [24], and the high-level parameters can be obfuscated by implementation details [8]. It can be a time-consuming and frustrating experience to debug, reproduce, and adapt existing models for DIA, and many researchers who would beneﬁt the most from using these methods lack the technical background to implement them from scratch. 2) Document images contain diverse and disparate patterns across domains, and customized training is often required to achieve a desirable detection accuracy. Currently there is no full-ﬂedged infrastructure for easily curating the target document image datasets and ﬁne-tuning or re-training the models. 3) DIA usually requires a sequence of models and other processing to obtain the ﬁnal outputs. Often research teams use DL models and then perform further document analyses in separate processes, and these pipelines are not documented in any central location (and often not documented at all). This makes it diﬃcult for research teams to learn about how full pipelines are implemented and leads them to invest signiﬁcant resources in reinventing the DIA wheel .\n"
     ]
    }
   ],
   "source": [
    "print(\"\\n\\n\".join([str(el) for el in elements][5:15]))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e3a8e7f4",
   "metadata": {},
   "source": [
    "The `unstructured` library also includes partitioning bricks targeted at specific document types. The `partition` brick uses these document-specific partitioning bricks under the hood. There are a few reasons you may want to use a document-specific partitioning brick instead of `partition`:\n",
    "\n",
    "1. If you already know the document type, filetype detection is unnecessary. Using the document-specific brick directly will make your program run faster.\n",
    "2. Fewer dependencies. You don't need to install `libmagic` for filetype detection if you're only using document-specific bricks.\n",
    "3. Additional features. The API for `partition` is the least common denominator for all document types. Certain document-specific brick include extra features that you may want to take advantage of. For example, `partition_html` allows you to pass in a URL so you don't have to store the `.html` file locally.\n",
    "\n",
    "Currently, the partitioning bricks we support in `unstructured` are:\n",
    "\n",
    "- `partition_docx`\n",
    "    - Works on `.docx` files. Does not yet work on older `.doc` files.\n",
    "- `partition_pptx`\n",
    "    - Works on `.pptx` files. Does not yet work on older `.ppt` files.\n",
    "- `partition_html`\n",
    "    - Works on `.html` files.\n",
    "    - Can pass in the HTML document as a string using the `text` kwarg.\n",
    "    - Can pass in the URL for an HTML document using the `url` kwarg.\n",
    "- `partition_pdf`\n",
    "    - Works on `.pdf` files. Partitions the document using a document image analysis model.\n",
    "    - If `url=None`, the model will run locally. If you pass in a URL, the brick will make a network call\n",
    "      to a hosted model inference API. There is also an optional `token` kwarg for passing in an authentication token.\n",
    "- `partition_image`\n",
    "    - Has the same API as `partition_pdf`. Works on `.jpg` and `.png` files.\n",
    "- `partition_email`\n",
    "    - Works on `.eml` files. Most common email clients (i.e. Gmail, Microsoft Outlook) allow users to export emails in\n",
    "      `.eml` format.\n",
    "    - Parses the `text/html` content from the email by default. If you set `content_source=\"text/plain\"`, the brick will parse the plain text instead.\n",
    "    - If you set `include_headers=True`, the output will include information from the email header.\n",
    "    - You can pass in the email as a string using the `text` kwarg.\n",
    "- `partition_text`\n",
    "    - Works on plain text files.\n",
    "    - You can pass in the document as a string using the `text` kwarg.\n",
    "\n",
    "\n",
    "See the [`unstructured` docs](https://unstructured-io.github.io/unstructured/bricks.html#partition-docx) for a full list of options. Below we see an example of how to partition a document directly with the URL using the `partition_html` function.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "b7ce3fa8",
   "metadata": {},
   "outputs": [],
   "source": [
    "from unstructured.partition.html import partition_html\n",
    "\n",
    "url = \"https://www.cnn.com/2023/01/30/sport/empire-state-building-green-philadelphia-eagles-spt-intl/index.html\"\n",
    "elements = partition_html(url=url)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "ab6d9307",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CNN\n",
      "         —\n",
      "\n",
      "The Empire State Building was lit in green and white to celebrate the Philadelphia Eagles' victory in the NFC Championship game on Sunday — a decision that's sparked a bit of a backlash in the Big Apple.\n",
      "\n",
      "The Eagles advanced to the Super Bowl for the first time since 2018 after defeating the San Francisco 49ers 31-7, and the Empire State Building later tweeted how it was marking the occasion.\n",
      "\n",
      "Fly @Eagles Fly! We're going Green and White in honor of the Eagles NFC Championship Victory. pic.twitter.com/RNiwbCIkt7— Empire State Building (@EmpireStateBldg)\n",
      "\n",
      "January 29, 2023\n",
      "\n",
      "But given the fierce rivalry between the Eagles and the New York Giants, who the Super Bowl-bound team had comfortably defeated in the previous round of the NFL Playoffs, many were left questioning the move.\n",
      "\n",
      "Did y'all lose a bet, ESPN contributor Mina Kimes asked in response to the tweet, while Giants running back Matt Breida also expressed his disbelief.\n",
      "\n",
      "SMHð¤¦ð¾âï¸— Matt Breida (@MattBreida)\n",
      "\n",
      "January 30, 2023\n",
      "\n",
      "As the representative for the Empire State Building, and a diehard Giants fan, let me be on the record saying that this is absolutely ridiculous, said New York City councilman Keith Powers.\n",
      "\n",
      "The Giants' Twitter account also acknowledged the divisive decision, writing: I'm just here for the comments.\n",
      "\n",
      "The Empire State Building, whose original tweet honoring the Eagles was viewed nearly 30 million at the time of writing, said the color switch hurt us more than it hurt you — but only after mocking another tweet calling the New York landmark lame.\n",
      "\n",
      "The building was later lit in red to celebrate the Kansas City Chiefs' AFC Championship win against the Cincinnati Bengals.\n",
      "\n",
      "In Philadelphia, meanwhile, Eagles fans poured onto the streets on Sunday night. Large crowds gathered in the city as people climbed up light posts, street signs, and on top of a bus stop canopy.\n",
      "\n",
      "The city announced street closures and vehicle restrictions in Philadelphia's city center due to Eagles celebratory activity between 8th to 20th streets and Race to Lombard streets, the city's Office of Emergency Management tweeted on Sunday night.\n",
      "\n",
      "Philadelphians, let's celebrate joyously, safely, and respectfully and show the same love we have for our team to our city. Go Birds! Mayor Jim Kenney tweeted.\n",
      "\n",
      "The Eagles and the Chiefs face off in Super Bowl LVII on February 12.\n"
     ]
    }
   ],
   "source": [
    "print(\"\\n\\n\".join([str(el) for el in elements]))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e51c26ed",
   "metadata": {},
   "source": [
    "## Cleaning bricks <a id=\"cleaning\"></a>\n",
    "\n",
    "As part of data preparation for an NLP model, it's common to need to clean up your data prior to passing it into the model. If there's unwanted content in your output, it could impact the quality of your NLP model. To help with this, the `unstructured` library includes cleaning bricks to help users sanitize output before sending it to downstream applications. You can check out our [documentation](https://unstructured-io.github.io/unstructured/bricks.html#cleaning) for a full list of cleaning bricks.\n",
    "\n",
    "Some cleaning bricks apply automatically. In the example above, the output `Philadelphia Eaglesâ\\x80\\x99 victory` automatically gets converted to `Philadelphia Eagles' victory` in `partition_html` using the `replace_unicode_quotes` cleaning brick. You can see how that works in the code snippet below:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "a1c4ba19",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"Philadelphia Eagles' victory\""
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from unstructured.cleaners.core import replace_unicode_quotes\n",
    "\n",
    "replace_unicode_quotes(\"Philadelphia Eaglesâ\\x80\\x99 victory\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "db2391ce",
   "metadata": {},
   "source": [
    "Document elements in `unstructured` include an `apply` method that allow you to apply the text cleaning to the document element without instantiating a new element. The `apply` method expects a callable that takes a string as input and produces another string as output. In the example below, we invoke the `replace_unicode_quotes` cleaning brick using the `apply` method."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "215c4b35",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Philadelphia Eagles' victory\n"
     ]
    }
   ],
   "source": [
    "from unstructured.documents.elements import Text\n",
    "\n",
    "element = Text(\"Philadelphia Eaglesâ\\x80\\x99 victory\")\n",
    "element.apply(replace_unicode_quotes)\n",
    "print(element)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "358e149b",
   "metadata": {},
   "source": [
    "Since a cleaning brick is just a `str -> str` function, users can also easily include their own cleaning bricks for custom data preparation tasks. In the example below, we partition a Russian offensive campaign assessment from the institute of the study of war and remove citations, which are not natural language text that we want to include for model training purposes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "ae048814",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = \"https://www.understandingwar.org/backgrounder/russian-offensive-campaign-assessment-february-8-2023\"\n",
    "elements = partition_html(url=url)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "4211194b",
   "metadata": {},
   "outputs": [],
   "source": [
    "from unstructured.documents.elements import NarrativeText\n",
    "\n",
    "narrative_text = [el for el in elements if isinstance(el, NarrativeText)][2:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "3abd4280",
   "metadata": {},
   "outputs": [],
   "source": [
    "import re\n",
    "\n",
    "remove_citations = lambda text: re.sub(\"\\[\\d{1,3}\\]\", \"\", text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "3327feda",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'[1]\\xa0Geolocated combat footage has confirmed Russian gains in the Dvorichne area northwest of Svatove.'"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "narrative_text[0].text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "02eb95ae",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\xa0Geolocated combat footage has confirmed Russian gains in the Dvorichne area northwest of Svatove.'"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "narrative_text[0].apply(remove_citations)\n",
    "narrative_text[0].text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "b755cc86",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Russian officials continue to propose measures to prepare Russia’s military industry for a protracted war in Ukraine while also likely setting further conditions for sanctions evasion.\\xa0Russian Prime Minister Mikhail Mishustin stated on February 8 that the Russian government will subsidize investment projects for the modernization of enterprises operating in the interests of the Russian military and will allocate significant funds for manufacturing new military equipment.\\xa0Mishustin also stated that the Russian government would extend benefits to Russian entrepreneurs who support the Russian military, including extended payment periods on rented federal property.\\xa0The Kremlin likely intends these measures to augment its overarching effort to gradually prepare Russia’s military industry for a protracted war in Ukraine while avoiding a wider economic mobilization that would create further domestic economic disruptions and corresponding discontent.'"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "narrative_text[6].apply(remove_citations)\n",
    "narrative_text[6].text"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "578a6d10",
   "metadata": {},
   "source": [
    "As we can see, the citations have been removed. After removing the citations, we still have extra whitespace represented by `\\xa0`. We can clean that up using the `clean_extra_whitespace` cleaning brick."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "7d65d7c8",
   "metadata": {},
   "outputs": [],
   "source": [
    "from unstructured.cleaners.core import clean_extra_whitespace\n",
    "\n",
    "narrative_text[0].apply(clean_extra_whitespace)\n",
    "narrative_text[6].apply(clean_extra_whitespace)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "a37f9bad",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Geolocated combat footage has confirmed Russian gains in the Dvorichne area northwest of Svatove.'"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "narrative_text[0].text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "25245bc1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Russian officials continue to propose measures to prepare Russia’s military industry for a protracted war in Ukraine while also likely setting further conditions for sanctions evasion. Russian Prime Minister Mikhail Mishustin stated on February 8 that the Russian government will subsidize investment projects for the modernization of enterprises operating in the interests of the Russian military and will allocate significant funds for manufacturing new military equipment. Mishustin also stated that the Russian government would extend benefits to Russian entrepreneurs who support the Russian military, including extended payment periods on rented federal property. The Kremlin likely intends these measures to augment its overarching effort to gradually prepare Russia’s military industry for a protracted war in Ukraine while avoiding a wider economic mobilization that would create further domestic economic disruptions and corresponding discontent.'"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "narrative_text[6].text"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3b99ec0b",
   "metadata": {},
   "source": [
    "Now the text is clean and formatted how we'd like it for our model training application. The best way to invoke a series of cleaning bricks is to loop over the elements and call `apply` with all of your bricks. For example, we can apply the cleaning bricks to all of the elements from the ISW article with the following code:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "0218cc7a",
   "metadata": {},
   "outputs": [],
   "source": [
    "for element in narrative_text:\n",
    "    element.apply(remove_citations)\n",
    "    element.apply(clean_extra_whitespace)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6ecb360d",
   "metadata": {},
   "source": [
    "## Staging bricks <a id=\"staging\"></a>\n",
    "\n",
    "The final step in the process is to prepare your data for ingestion into downstream systems. We include staging bricks in the `unstructured` package to help with that. Staging bricks accept a list of document elements as input and return an appropriately formatted dictionary as output. In the example below, we get our narrative text samples prepared for ingestion into LabelStudio using the `stage_for_label_studio` brick. We can take this data and directly upload it into LabelStudio to quickly get started with an NLP labeling task."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "21819f56",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[\n",
      "    {\n",
      "        \"data\": {\n",
      "            \"text\": \"Geolocated combat footage has confirmed Russian gains in the Dvorichne area northwest of Svatove.\",\n",
      "            \"ref_id\": \"c311a941b80429f2ba0b6a2137f7315e\"\n",
      "        }\n",
      "    },\n",
      "    {\n",
      "        \"data\": {\n",
      "            \"text\": \"Russian military command additionally appears to have fully committed elements of several conventional divisions to decisive offensive operations along the Svatove-Kreminna line, as ISW previously reported.\",\n",
      "            \"ref_id\": \"79748ec84695bd88f41b13e98eae53be\"\n",
      "        }\n",
      "    }\n",
      "]\n"
     ]
    }
   ],
   "source": [
    "import json\n",
    "from unstructured.staging.label_studio import stage_for_label_studio\n",
    "\n",
    "output = stage_for_label_studio(narrative_text)\n",
    "print(json.dumps(output[:2], indent=4))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "94e74c2c",
   "metadata": {},
   "source": [
    "Currently, `unstructured` supports the following staging bricks:\n",
    "\n",
    "- `stage_for_argilla`\n",
    "- `stage_for_transformers`\n",
    "- `stage_for_label_studio`\n",
    "- `stage_for_prodigy`\n",
    "- `stage_for_label_box`\n",
    "- `stage_for_datasaur`"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "54477e73",
   "metadata": {},
   "source": [
    "Also included among the staging bricks are functions for converting a list of document elements to a dictionary, CSV, or dataframe. These helper functions are useful if you just want the text and don't need the data pre-formatted for a particular downstream tool. These functions include:\n",
    "\n",
    "- `convert_to_isd`\n",
    "- `convert_to_isd_csv`\n",
    "- `convert_to_dataframe`\n",
    "\n",
    "The \"ISD\" in these functions refers to \"initial structured data\", our standard dictionary representation of text elements. Here we convert the list of elements to a dictionary and a dataframe."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "6d5cf8cf",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[\n",
      "    {\n",
      "        \"text\": \"Skip to main content\",\n",
      "        \"type\": \"Title\"\n",
      "    },\n",
      "    {\n",
      "        \"text\": \"(function(d){\\n  var js, id = 'facebook-jssdk'; if (d.getElementById(id)) {return;}\\n  js = d.createElement('script'); js.id = id; js.async = true;\\n  js.src = \\\"//connect.facebook.net/en_US/all.js#xfbml=1\\\";\\n  d.getElementsByTagName('head')[0].appendChild(js);\\n}(document));\",\n",
      "        \"type\": \"NarrativeText\"\n",
      "    }\n",
      "]\n"
     ]
    }
   ],
   "source": [
    "from unstructured.staging.base import convert_to_isd\n",
    "\n",
    "isd = convert_to_isd(elements)\n",
    "print(json.dumps(isd[:2], indent=4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "706cc9c7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>type</th>\n",
       "      <th>text</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Title</td>\n",
       "      <td>Skip to main content</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>NarrativeText</td>\n",
       "      <td>(function(d){\\n  var js, id = 'facebook-jssdk'...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Title</td>\n",
       "      <td>Search form</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>ListItem</td>\n",
       "      <td>Home</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>ListItem</td>\n",
       "      <td>Who We Are</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            type                                               text\n",
       "0          Title                               Skip to main content\n",
       "1  NarrativeText  (function(d){\\n  var js, id = 'facebook-jssdk'...\n",
       "2          Title                                        Search form\n",
       "3       ListItem                                               Home\n",
       "4       ListItem                                         Who We Are"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from unstructured.staging.base import convert_to_dataframe\n",
    "\n",
    "df = convert_to_dataframe(elements)\n",
    "df.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e572f082",
   "metadata": {},
   "source": [
    "If you have a dictionary in ISD format, you can convert back to a list of elements using the `isd_to_elements` function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "b2c1282e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<unstructured.documents.elements.Title at 0x28bf910a0>,\n",
       " <unstructured.documents.elements.NarrativeText at 0x28bf91460>]"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from unstructured.staging.base import isd_to_elements\n",
    "\n",
    "isd_to_elements(isd[:2])"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
